home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / xmsbcp11.zip / XMS30.TXT < prev   
Text File  |  1997-04-13  |  48KB  |  1,209 lines

  1. eXtended Memory Specification (XMS), ver 3.0
  2.  
  3.  
  4. January 1991
  5.  
  6.  
  7. Copyright (c) 1988, Microsoft Corporation, Lotus Development
  8. Corporation, Intel Corporation, and AST Research, Inc.
  9.  
  10. Microsoft Corporation
  11. Box 97017
  12.  
  13. One Microsoft Way
  14. Redmond, WA 98073
  15.  
  16. LOTUS (R)
  17. INTEL (R)
  18. MICROSOFT (R)
  19. AST (R) Research
  20.  
  21. This specification was jointly developed by Microsoft Corporation,
  22. Lotus Development Corporation, Intel Corporation,and AST Research,
  23. Inc. Although it has been released into the public domain and is not
  24. confidential or proprietary, the specification is still the copyright
  25. and property of Microsoft Corporation, Lotus Development Corporation,
  26. Intel Corporation, and AST Research, Inc.
  27.  
  28. Disclaimer of Warranty
  29.  
  30. MICROSOFT CORPORATION, LOTUS DEVELOPMENT CORPORATION, INTEL CORPORATION, 
  31. AND AST RESEARCH, INC., EXCLUDE ANY AND ALL IMPLIED WARRANTIES, 
  32. INCLUDING WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  33. PURPOSE. NEITHER MICROSOFT NOR LOTUS NOR INTEL NOR AST RESEARCH MAKE 
  34. ANY WARRANTY OF REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT 
  35. TO THIS SPECIFICATION, ITS QUALITY, PERFORMANCE, MERCHANTABILITY, OR 
  36. FITNESS FOR A PARTICULAR PURPOSE.  NEITHER MICROSOFT NOR LOTUS NOR 
  37. INTEL NOR AST RESEARCH SHALL HAVE ANY LIABILITY FOR SPECIAL, INCIDENTAL, 
  38. OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RESULTING FROM THE USE OR 
  39. MODIFICATION OF THIS SPECIFICATION.
  40.  
  41. This specification uses the following trademarks:
  42.  
  43. Intel is a registered trademark of Intel Corporation,
  44. Microsoft is a registered trademark of Microsoft Corporation, 
  45. Lotus is a registered trademark of Lotus Development Corporation, and 
  46. AST is a registered trademark of AST Research, Inc.
  47.  
  48.  
  49.                 Extended Memory Specification
  50.  
  51.     The purpose of this document is to define the Extended Memory 
  52. Specification (XMS) version 3.00 for MS-DOS.  XMS allows DOS programs 
  53. to utilize additional memory found in Intel's 80286 and 80386 based 
  54. machines in a consistent, machine independent manner.  With some 
  55. restrictions, XMS adds almost 64K to the 640K which DOS programs can 
  56. access directly.  Depending on available hardware, XMS may provide
  57. even more memory to DOS programs.  XMS also provides DOS programs with 
  58. a standard method of storing data in extended memory.
  59.  
  60.      To be considered fully XMS 3.0 compliant, all calls except those 
  61. associated with UMB support must be implemented.  UMB functions 10h, 
  62. 11h and 12h are optional for XMS 3.0 and may return the Function Not 
  63. Implemented error code, 80h.
  64.  
  65. DEFINITIONS:
  66. ------------
  67.  
  68.  Extended Memory:
  69.    Memory in 80286 and 80386 based machines which is located above 
  70.    the 1MB address boundary.
  71.  
  72.  High Memory Area (HMA):
  73.   The first 64K of extended memory.  The High Memory Area is unique 
  74.   because code can be executed in it while in real mode.  The HMA 
  75.   officially starts at FFFF:10h and ends at FFFF:FFFFh making it 
  76.   64K-16 bytes in length.
  77.  
  78.  Upper Memory Blocks (UMBs):
  79.   Blocks of memory available on some 80x86 based machines which 
  80.   are located between DOS's 640K limit and the 1MB address boundary.  
  81.   The number, size, and location of these blocks vary widely 
  82.   depending upon the types of hardware adapter cards installed in 
  83.   the machine.
  84.  
  85.  Extended Memory Blocks (EMBs):
  86.   Blocks of extended memory located above the HMA which can only be 
  87.   used for data storage.
  88.  
  89.  A20 Line:
  90.   The 21st address line of 80x86 CPUs.  Enabling the A20 line allows 
  91.   access to the HMA.
  92.  
  93.  XMM:
  94.   An Extended Memory Manager.  A DOS device driver which implements 
  95.   XMS.  XMMs are machine specific but allow programs to use extended 
  96.   memory in a machine-independent manner.
  97.  
  98.  HIMEM.SYS:
  99.   The Extended Memory Manager currently being distributed by
  100.   Microsoft.
  101.  
  102.  
  103. Helpful Diagram:
  104.  
  105.    _____________________________________
  106.   |                                     |   Top of Memory
  107.   |                                     |
  108.   |                                     |
  109.   |                /\                   |
  110.   |               /||\                  |
  111.   |                ||                   |
  112.   |                ||                   |
  113.   |                                     |
  114.   |_____________________________________|
  115.   |                                     |
  116.   |                                     |
  117.   |                                     |
  118.   |  Possible Extended Memory Block     |
  119.   |                                     |
  120.   |                                     |
  121.   |_____________________________________|
  122.   |                                     |
  123.   |                                     |   
  124.   |                ||                   |
  125.   |                ||                   |
  126.   |               \||/                  |
  127.   |                \/                   |
  128.   |                                     |
  129.   |                                     |
  130.   |   Other EMBs could exist above      |
  131.   |        1088K  (1MB+64K)             |
  132.   |                                     |
  133.   |                                     |
  134.   |_____________________________________|   1088K
  135.   |                                     |
  136.   |                                     |
  137.   |       The High Memory Area          |
  138.   |                                     |
  139.   |                                     |
  140.   |_____________________________________|   1024K or 1MB
  141.   |                                     |
  142.   |                                     |
  143.   |                /\                   |
  144.   |               /||\                  |
  145.   |                ||                   |
  146.   |                ||                   |
  147.   |_____________________________________|
  148.   |                                     |
  149.   |   Possible Upper Memory Block       |
  150.   |_____________________________________|
  151.   |                                     |   
  152.   |                ||                   |
  153.   |                ||                   |
  154.   |               \||/                  |
  155.   |                \/                   |
  156.   |                                     |
  157.   |                                     |
  158.   |  Other UMBs could exist between     |
  159.   |          640K and 1MB               |
  160.   |                                     |
  161.   |_____________________________________|   640K
  162.   |                                     |
  163.   |                                     |        
  164.   |                                     |
  165.   |                                     |
  166.   |                                     |
  167.   |                                     |
  168.   |                                     |
  169.   |                                     |
  170.   |    Conventional or DOS Memory       |
  171.   |                                     |
  172.   |                                     |
  173.   |                                     |
  174.   |                                     |
  175.   |                                     |
  176.   |                                     |
  177.   |_____________________________________|   0K
  178.  
  179.  
  180.  
  181. DRIVER INSTALLATION:
  182. --------------------
  183.  
  184.     An XMS driver is installed by including a DEVICE=statement in the
  185. machine's CONFIG.SYS file.  It must be installed prior to any other
  186. devices or TSRs which use it.  An optional parameter after the driver's
  187. name (suggested name "/HMAMIN=") indicates the minimum amount of space 
  188. in the HMA a program can use.  Programs which use less than the minimum
  189. will not be placed in the HMA.  See "Prioritizing HMA Usage" below for 
  190. more information.  A second optional parameter (suggested name 
  191. "/NUMHANDLES=") allows users to specify the maximum number of extended
  192. memory blocks which may be allocated at any time.
  193.  
  194.     NOTE: XMS requires DOS version 3.00 or above.
  195.  
  196.  
  197. THE PROGRAMMING API:
  198. --------------------
  199.  
  200.     The XMS API Functions are accessed via the XMS driver's Control 
  201. Function.  The address of the Control Function is determined via INT
  202. 2Fh.  First, a program should determine if an XMS driver is installed.
  203. Next, it should retrieve the address of the driver's Control Function.  
  204. It can then use any of the available XMS functions.  The functions 
  205. are divided into several groups:
  206.  
  207.         1. Driver Information Functions (0h)
  208.         2. HMA Management Functions (1h-2h)
  209.         3. A20 Management Functions (3h-7h)
  210.         4. Extended Memory Management Functions (8h-Fh)
  211.         5. Upper Memory Management Functions (10h-11h)
  212.  
  213.  
  214. DETERMINING IF AN XMS DRIVER IS INSTALLED:
  215. ------------------------------------------
  216.  
  217.     The recommended way of determining if an XMS driver is installed 
  218. is to set AH=43h and AL=00h and then execute INT 2Fh.  If an XMS
  219. driver is available,80h will be returned in AL.
  220.  
  221.     Example:
  222.             ; Is an XMS driver installed?
  223.             mov     ax,4300h
  224.             int     2Fh
  225.             cmp     al,80h
  226.             jne     NoXMSDriver
  227.  
  228.  
  229. CALLING THE API FUNCTIONS:
  230. --------------------------
  231.  
  232.     Programs can execute INT 2Fh with AH=43h and AL=10h to obtain the 
  233. address of the driver's control function.  The address is returned
  234. in ES:BX.  This function is called to access all of the XMS functions.  
  235. It should be called with AH set to the number of the API function 
  236. requested.  The API function will put a success code of 0001h or 0000h 
  237. in AX.  If the function succeeded (AX=0001h), additional information 
  238. may be passed back in BX and DX.  If the function failed (AX=0000h), 
  239. an error code may be returned in BL.  Valid error codes have their 
  240. high bit set.  Developers should keep in mind that some of the XMS API 
  241. functions may not be implemented by all drivers and will return failure 
  242. in all cases.
  243.  
  244.     Example:
  245.             ; Get the address of the driver's control function
  246.             mov     ax,4310h
  247.             int     2Fh
  248.             mov     word ptr [XMSControl],bx      ;XMSControl is a DWORD
  249.             mov     word ptr [XMSControl+2],es
  250.  
  251.             ; Get the XMS driver's version number
  252.             mov     ah,00h
  253.             call    [XMSControl]    ; Get XMS Version Number
  254.  
  255.     NOTE: Programs should make sure that at least 256 bytes of 
  256.           stack space is available before calling XMS API functions.
  257.  
  258.  
  259. API FUNCTION DESCRIPTIONS:
  260. --------------------------
  261.  
  262.     The following XMS API functions are available:
  263.  
  264.        0h)  Get XMS Version Number
  265.        1h)  Request High Memory Area
  266.        2h)  Release High Memory Area
  267.        3h)  Global Enable A20
  268.        4h)  Global Disable A20
  269.        5h)  Local Enable A20
  270.        6h)  Local Disable A20
  271.        7h)  Query A20
  272.        8h)  Query Free Extended Memory
  273.        9h)  Allocate Extended Memory Block
  274.        Ah)  Free Extended Memory Block
  275.        Bh)  Move Extended Memory Block
  276.        Ch)  Lock Extended Memory Block
  277.        Dh)  Unlock Extended Memory Block
  278.        Eh)  Get Handle Information
  279.        Fh)  Reallocate Extended Memory Block
  280.       10h)  Request Upper Memory Block
  281.       11h)  Release Upper Memory Block
  282.       12h) Realloc Upper Memory Block
  283.       88h) Query any Free Extended Memory
  284.       89h) Allocate any Extended Memory Block
  285.       8Eh) Get Extended EMB Handle
  286.       8Fh) Realloc any Extended Memory
  287.  
  288. Each is described below.
  289.  
  290.  
  291. Get XMS Version Number (Function 00h):
  292. --------------------------------------
  293.  
  294.     ARGS:   AH = 00h
  295.     RETS:   AX = XMS version number
  296.             BX = Driver internal revision number
  297.             DX = 0001h if the HMA exists, 0000h otherwise
  298.     ERRS:   None
  299.  
  300.     This function returns with AX equal to a 16-bit BCD number 
  301. representing the revision of the DOS Extended Memory Specification 
  302. which the driver implements (e.g. AX=0235h would mean that the 
  303. driver implemented XMS version 2.35).  BX is set equal to the 
  304. driver's internal revision number mainly for debugging purposes.  
  305. DX indicates the existence of the HMA (not its availability) and 
  306. is intended mainly for installation programs.
  307.  
  308.     NOTE: This document defines version 3.00 of the specification.
  309.  
  310.  
  311. Request High Memory Area (Function 01h):
  312. ----------------------------------------
  313.  
  314.     ARGS:   AH = 01h
  315.           If the caller is a TSR or device driver,
  316.             DX = Space needed in the HMA by the caller in bytes
  317.           If the caller is an application program,
  318.             DX = FFFFh
  319.     RETS:   AX = 0001h if the HMA is assigned to the caller, 
  320.                  0000h otherwise
  321.     ERRS:   BL = 80h if the function is not implemented
  322.             BL = 81h if a VDISK device is detected
  323.             BL = 90h if the HMA does not exist
  324.             BL = 91h if the HMA is already in use
  325.             BL = 92h if DX is less than the /HMAMIN= parameter
  326.  
  327.     This function attempts to reserve the 64K-16 byte high
  328. memory area for the caller.  If the HMA is currently unused, the 
  329. caller's size parameter is compared to the /HMAMIN= parameter on the 
  330. driver's command line.  If the value passed by the caller is greater 
  331. than or equal to the amount specified by the driver's parameter, the 
  332. request succeeds.  This provides the ability to ensure that programs 
  333. which use the HMA efficiently have priority over those which do not.
  334.  
  335.     NOTE: See the sections "Prioritizing HMA Usage" and "High 
  336.           Memory Area Restrictions" below for more information.
  337.  
  338.  
  339. Release High Memory Area (Function 02h):
  340. ----------------------------------------
  341.  
  342.     ARGS:   AH = 02h
  343.     RETS:   AX = 0001h if the HMA is successfully released,
  344.                  0000h otherwise
  345.     ERRS:   BL = 80h if the function is not implemented
  346.             BL = 81h if a VDISK device is detected
  347.             BL = 90h if the HMA does not exist
  348.             BL = 93h if the HMA was not allocated
  349.  
  350.     This function releases the high memory area and allows
  351. other programs to use it.  Programs which allocate the HMA must 
  352. release it before exiting.  When the HMA has been released, any code 
  353. or data stored in it becomes invalid and should not be accessed.
  354.  
  355.  
  356. Global Enable A20 (Function 03h):
  357. ---------------------------------
  358.  
  359.     ARGS:   AH = 03h
  360.     RETS:   AX = 0001h if the A20 line is enabled, 
  361.                  0000h otherwise
  362.     ERRS:   BL = 80h if the function is not implemented
  363.             BL = 81h if a VDISK device is detected
  364.             BL = 82h if an A20 error occurs
  365.  
  366.     This function attempts to enable the A20 line.  It should only be 
  367. used by programs which have control of the HMA.  The A20 line
  368. should be turned off via Function 04h (Global Disable A20) before a 
  369. program releases control of the system.
  370.  
  371.     NOTE: On many machines, toggling the A20 line is a relatively 
  372.           slow operation.
  373.  
  374.  
  375. Global Disable A20 (Function 04h):
  376. ----------------------------------
  377.  
  378.     ARGS:   AH = 04h
  379.     RETS:   AX = 0001h if the A20 line is disabled, 
  380.                  0000h otherwise
  381.     ERRS:   BL = 80h if the function is not implemented
  382.             BL = 81h if a VDISK device is detected
  383.             BL = 82h if an A20 error occurs
  384.             BL = 94h if the A20 line is still enabled
  385.  
  386.     This function attempts to disable the A20 line.  It should only 
  387. be used by programs which have control of the HMA.  The A20 line
  388. should be disabled before a program releases control of the system.
  389.  
  390.     NOTE: On many machines, toggling the A20 line is a relatively 
  391.           slow operation.
  392.  
  393.  
  394. Local Enable A20 (Function 05h):
  395. --------------------------------
  396.  
  397.     ARGS:   AH = 05h
  398.     RETS:   AX = 0001h if the A20 line is enabled, 
  399.                  0000h otherwise
  400.     ERRS:   BL = 80h if the function is not implemented
  401.             BL = 81h if a VDISK device is detected
  402.             BL = 82h if an A20 error occurs
  403.  
  404.     This function attempts to enable the A20 line.  It should only 
  405. be used by programs which need direct access to extended memory.
  406. Programs which use this function should call Function 06h (Local 
  407. Disable A20) before releasing control of the system.
  408.  
  409.     NOTE: On many machines, toggling the A20 line is a relatively 
  410.           slow operation.
  411.  
  412.  
  413. Local Disable A20 (Function 06h):
  414. ---------------------------------
  415.  
  416.     ARGS:   AH = 06h
  417.     RETS:   AX = 0001h if the function succeeds, 
  418.                  0000h otherwise
  419.     ERRS:   BL = 80h if the function is not implemented
  420.             BL = 81h if a VDISK device is detected
  421.             BL = 82h if an A20 error occurs
  422.             BL = 94h if the A20 line is still enabled
  423.  
  424.     This function cancels a previous call to Function 05h (Local 
  425. Enable A20).  It should only be used by programs which need direct
  426. access to extended memory.  Previous calls to Function 05h must be
  427. canceled before releasing control of the system.
  428.  
  429.     NOTE: On many machines, toggling the A20 line is a relatively 
  430.           slow operation.
  431.  
  432.  
  433. Query A20 (Function 07h):
  434. -------------------------
  435.  
  436.     ARGS:   AH = 07h
  437.     RETS:   AX = 0001h if the A20 line is physically enabled, 
  438.                  0000h otherwise
  439.     ERRS:   BL = 00h if the function succeeds
  440.             BL = 80h if the function is not implemented
  441.             BL = 81h if a VDISK device is detected
  442.  
  443.     This function checks to see if the A20 line is physically enabled.  
  444. It does this in a hardware independent manner by seeing if "memory 
  445. wrap" occurs.
  446.  
  447.  
  448. Query Free Extended Memory (Function 08h):
  449. ------------------------------------------
  450.  
  451.     ARGS:   AH = 08h
  452.     RETS:   AX = Size of the largest free extended memory block 
  453.                  in K-bytes
  454.             DX = Total amount of free extended memory in K-bytes
  455.     ERRS:   BL = 80h if the function is not implemented
  456.             BL = 81h if a VDISK device is detected
  457.             BL = A0h if all extended memory is allocated
  458.  
  459.     This function returns the size of the largest available extended memory
  460. block in the system.
  461.  
  462.     NOTE: The 64K HMA is not included in the returned value even if it 
  463.           is not in use.
  464.  
  465.  
  466. Allocate Extended Memory Block (Function 09h):
  467. ----------------------------------------------
  468.  
  469.     ARGS:   AH = 09h
  470.             DX = Amount of extended memory being requested 
  471.                  in K-bytes
  472.     RETS:   AX = 0001h if the block is allocated, 
  473.                  0000h otherwise
  474.             DX = 16-bit handle to the allocated block
  475.     ERRS:   BL = 80h if the function is not implemented
  476.             BL = 81h if a VDISK device is detected
  477.             BL = A0h if all available extended memory is allocated
  478.             BL = A1h if all available extended memory handles
  479.                  are in use
  480.  
  481.     This function attempts to allocate a block of the given
  482. size out of the pool of free extended memory.  If a block is available, 
  483. it is reserved for the caller and a 16-bit handle to that block is
  484. returned.  The handle should be used in all subsequent extended memory 
  485. calls.  If no memory was allocated, the returned handle is null.
  486.  
  487.     NOTE: Extended memory handles are scarce resources.   Programs 
  488.           should try to allocate as few as possible at any one time.
  489.           When all of a driver's handles are in use, any free 
  490.           extended memory is unavailable.
  491.  
  492.  
  493. Free Extended Memory Block (Function 0Ah):
  494. ------------------------------------------
  495.  
  496.     ARGS:   AH = 0Ah
  497.             DX = Handle to the allocated block which should be freed
  498.     RETS:   AX = 0001h if the block is successfully freed,
  499.                  0000h otherwise
  500.     ERRS:   BL = 80h if the function is not implemented
  501.             BL = 81h if a VDISK device is detected
  502.             BL = A2h if the handle is invalid
  503.             BL = ABh if the handle is locked
  504.  
  505.     This function frees a block of extended memory which was
  506. previously allocated using Function 09h (Allocate Extended Memory
  507. Block).  Programs which allocate extended memory should free their 
  508. memory blocks before exiting.  When an extended memory buffer is freed, 
  509. its handle and all data stored in it become invalid and should not be 
  510. accessed.
  511.  
  512.  
  513. Move Extended Memory Block (Function 0Bh):
  514. ------------------------------------------
  515.  
  516.     ARGS:   AH = 0Bh
  517.             DS:SI = Pointer to an Extended Memory Move 
  518.                     Structure (see below)
  519.     RETS:   AX = 0001h if the move is successful, 
  520.                  0000h otherwise
  521.     ERRS:   BL = 80h if the function is not implemented
  522.             BL = 81h if a VDISK device is detected
  523.             BL = 82h if an A20 error occurs
  524.             BL = A3h if the SourceHandle is invalid
  525.             BL = A4h if the SourceOffset is invalid
  526.             BL = A5h if the DestHandle is invalid
  527.             BL = A6h if the DestOffset is invalid
  528.             BL = A7h if the Length is invalid
  529.             BL = A8h if the move has an invalid overlap
  530.             BL = A9h if a parity error occurs
  531.  
  532.     Extended Memory Move Structure Definition:
  533.  
  534.      ExtMemMoveStruct    struc
  535.        Length              dd  ? ; 32-bit number of bytes to transfer
  536.        SourceHandle        dw  ? ; Handle of source block
  537.        SourceOffset        dd  ? ; 32-bit offset into source
  538.        DestHandle          dw  ? ; Handle ofdestination block
  539.        DestOffset          dd  ? ; 32-bit offset into destination block
  540.        ExtMemMoveStruct    ends
  541.  
  542.     This function attempts to transfer a block of data from one 
  543. location to another.  It is primarily intended for moving blocks of 
  544. data between conventional memory and extended memory, however it can 
  545. be used for moving blocks within conventional memory and within 
  546. extended memory.
  547.  
  548.     NOTE: If SourceHandle is set to 0000h, the SourceOffset is 
  549.           interpreted as a standard segment:offset pair which refers 
  550.           to memory that is directly accessible by the processor.  
  551.           The segment:offset pair is stored in Intel DWORD notation.  
  552.           The same is true for DestHandle and DestOffset.
  553.  
  554.           SourceHandle and DestHandle do not have to refer to
  555.           locked memory blocks.
  556.  
  557.           Length must be even.   Although not required, WORD-
  558.           aligned moves can be significantly faster on most machines.  
  559.           DWORD aligned move can be even faster on 80386 machines.
  560.  
  561.           If the source and destination blocks overlap, only
  562.           forward moves (i.e. where the source base is less than the
  563.           destination base) are guaranteed to work properly.
  564.        
  565.           Programs should not enable the A20 line before calling 
  566.           this function.  The state of the A20 line is preserved.
  567.  
  568.           This function is guaranteed to provide a reasonable
  569.           number of interrupt windows during long transfers.
  570.  
  571.  
  572. Lock Extended Memory Block (Function 0Ch):
  573. ------------------------------------------
  574.  
  575.     ARGS:   AH = 0Ch
  576.             DX = Extended memory block handle to lock
  577.     RETS:   AX = 0001h if the block is locked, 
  578.                  0000h otherwise
  579.          DX:BX = 32-bit physical address of the locked block
  580.     ERRS:   BL = 80h if the function is not implemented
  581.             BL = 81h if a VDISK device is detected
  582.             BL = A2h if the handle is invalid
  583.             BL = ACh if the block's lock count overflows
  584.             BL = ADh if the lock fails
  585.  
  586.     This function locks an extended memory block and returns
  587. its base address as a 32-bit physical address.  Locked memory blocks
  588. are guaranteed not to move.  The 32-bit pointer is only valid while 
  589. the block is locked.  Locked blocks should be unlocked as soon as 
  590. possible.
  591.  
  592.     NOTE: A block does not have to be locked before using
  593.           Function 0Bh (Move Extended Memory Block).
  594.  
  595.           "Lock counts" are maintained for EMBs.
  596.  
  597.  
  598. Unlock Extended Memory Block (Function 0Dh):
  599. --------------------------------------------
  600.  
  601.     ARGS:   AH = 0Dh
  602.             DX = Extended memory block handle to unlock
  603.     RETS:   AX = 0001h if the block is unlocked, 
  604.                  0000h otherwise
  605.     ERRS:   BL = 80h if the function is not implemented
  606.             BL = 81h if a VDISK device is detected
  607.             BL = A2h if the handle is invalid
  608.             BL = AAh if the block is not locked
  609.  
  610.     This function unlocks a locked extended memory block.
  611. Any 32-bit pointers into the block become invalid and should no 
  612. longer be used.
  613.  
  614.  
  615. Get EMB Handle Information (Function 0Eh):
  616. ------------------------------------------
  617.  
  618.     ARGS:   AH = 0Eh
  619.             DX = Extended memory block handle
  620.     RETS:   AX = 0001h if the block's information is found,
  621.                  0000h otherwise
  622.             BH = The block's lock count
  623.             BL = Number of free EMB handles in the system
  624.             DX = The block's length in K-bytes
  625.     ERRS:   BL = 80h if the function is not implemented
  626.             BL = 81h if a VDISK device is detected
  627.             BL = A2h if the handle is invalid
  628.  
  629.     This function returns additional information about an extended 
  630. memory block to the caller.
  631.  
  632.     NOTE: To get the block's base address, use Function 0Ch
  633.           (Lock Extended Memory Block).
  634.  
  635.  
  636. Reallocate Extended Memory Block (Function 0Fh):
  637. ------------------------------------------------
  638.  
  639.     ARGS:   AH = 0Fh
  640.             BX = New size for the extended memory block in K-bytes
  641.             DX = Unlocked extended memory block handle to reallocate
  642.     RETS:   AX = 0001h if the block is reallocated, 
  643.                  0000h otherwise
  644.     ERRS:   BL = 80h if the function is not implemented
  645.             BL = 81h if a VDISK device is detected
  646.             BL = A0h if all available extended memory is allocated
  647.             BL = A1h if all available extended memory handles
  648.                  are in use
  649.             BL = A2h if the handle is invalid
  650.             BL = ABh if the block is locked
  651.  
  652.     This function attempts to reallocate an unlocked extended memory 
  653. block so that it becomes the newly specified size.  If the new
  654. size is smaller than the old block's size, all data at the upper end 
  655. of the old block is lost.
  656.  
  657.  
  658. Request Upper Memory Block (Function 10h):
  659. ------------------------------------------
  660.  
  661.     ARGS:   AH = 10h
  662.             DX = Size of requested memory block in paragraphs
  663.     RETS:   AX = 0001h if the request is granted, 
  664.                  0000h otherwise
  665.             BX = Segment number of the upper memory block
  666.           If the request is granted,
  667.             DX = Actual size of the allocated block in paragraphs
  668.           Otherwise,
  669.             DX = Size of the largest available UMB in paragraphs
  670.     ERRS:   BL = 80h if the function is not implemented
  671.             BL = B0h if a smaller UMB is available
  672.             BL = B1h if no UMBs are available
  673.  
  674.     This function attempts to allocate an upper memory block to the 
  675. caller.  If the function fails, the size of the largest free UMB is
  676. returned in DX.
  677.  
  678.     NOTE: By definition UMBs are located below the 1MB address 
  679.           boundary.  The A20 Line does not need to be enabled 
  680.           before accessing an allocated UMB.
  681.  
  682.           UMBs are paragraph aligned.
  683.  
  684.           To determine the size of the largest available UMB,
  685.           attempt to allocate one with a size of FFFFh.
  686.  
  687.           UMBs are unaffected by EMS calls.
  688.  
  689.  
  690. Release Upper Memory Block (Function 11h):
  691. ------------------------------------------
  692.  
  693.     ARGS:   AH = 11h
  694.             DX = Segment number of the upper memory block
  695.     RETS:   AX = 0001h if the block was released, 
  696.                  0000h otherwise
  697.     ERRS:   BL = 80h if the function is not implemented
  698.             BL = B2h if the UMB segment number is invalid
  699.  
  700.     This function frees a previously allocated upper memory
  701. block.  When an UMB has been released, any code or data stored in 
  702. it becomes invalid and should not be accessed.
  703.  
  704.  
  705.  
  706. Reallocate Upper Memory Block (Function 12h):
  707. ---------------------------------------------
  708.  
  709.      ARGS:  AH = 12h
  710.             BX = New size for UMB in paragraphs
  711.             DX = Segment number of the UMB to reallocate
  712.      RETS:  AX = 0001h if the block was reallocated, 
  713.                  0000h otherwise
  714.      ERRS:  BL = 80h if the function is not implemented
  715.             BL = B0h if no UMB large enough to satisfy the request 
  716.                  is available.
  717.           In this event, 
  718.             DX = size of the largest UMB that is available.
  719.             
  720.             BL = B2h if the UMB segment number is invalid
  721.  
  722. This  function attempts to reallocate an Upper Memory Block to a 
  723. newly specified size.  If the new size is smaller than the old block's 
  724. size, all data at the upper end of the block is lost.
  725.  
  726.  
  727.  
  728. Super Extended Memory Support
  729. -----------------------------
  730.  
  731. These changes are intended to provide support for  extended memory pools 
  732. up to 4 Gb in size.  The current XMS API, since it uses 16-bit values 
  733. to specify block sizes in Kb, is limited to 64 Mb maximum block size.  
  734. Future machines are expected to support memory above 64 MB.
  735.  
  736. This support is implemented in the form of extensions to existing 
  737. functions, rather than entirely new entry points, to allow for more 
  738. efficient implementations.
  739.  
  740. Programs should generally use the existing functions, instead of these 
  741. extended ones, unless they have an explicit need to deal with memory 
  742. above 64 Mb.
  743.  
  744.  
  745. Query Any Free Extended Memory (Function 88h):
  746. ----------------------------------------------
  747.  
  748.  
  749.      Entry:
  750.             AH  = 88h
  751.      Exit:
  752.             EAX = Size of largest free extended memory block in Kb.
  753.             BL  = 00h if no error occurs, 
  754.                 = Error code, otherwise
  755.             ECX = Highest ending address of any memory block.
  756.             EDX = Total amount of free memory in Kb.
  757.      Errors:
  758.             BL  = 80h if the function is not implemented.
  759.             BL  = 81h if a VDISK device is detected.
  760.             BL  = A0h if all extended memory is allocated.
  761.  
  762.     This function uses 32-bit values to return the size of available 
  763. memory, thus allowing returns up to 4GByte.  Additionally, it returns 
  764. the highest known physical memory address, that is, the physical address 
  765. of the last byte of memory.  There may be discontinuities in the memory  
  766. map below this address.
  767.  
  768.     The memory pool reported on is the same as that reported on by 
  769. the existing Query Free Extended Memory function.  If the highest memory 
  770. address is not more than 64 Mb, then these two functions will return the 
  771. same results.
  772.  
  773.     Because of its reliance on 32-bit registers, this function is only 
  774. available on 80386 and higher processors.  XMS drivers on 80286 machines 
  775. should return error code 80h if this function is called.
  776.  
  777.     If error code 81h is returned, the value in ECX will still be valid.  
  778. If error code A0h is returned, EAX and EDX will be 0, and ECX will still 
  779. be valid.
  780.  
  781.  
  782. Allocate Any Extended Memory (Function 89h):
  783. --------------------------------------------
  784.  
  785.      Entry:
  786.             AH  = 89h
  787.             EDX = Amount of extended memory requested, in Kb.
  788.      Exit:
  789.             AX  = 0001h if the block is allocated, 
  790.                 = 0000h if not
  791.             DX  = Handle to allocated block.
  792.      Errors:
  793.             BL  = 80h if the function is not implemented.
  794.             BL  = 81h if a VDISK device is detected.
  795.             BL  = A0h if all available extended memory is allocated.
  796.             BL  = A1h if all available extended memory handles
  797.                   are in use.
  798.  
  799.     This function is similar to the existing Allocate Extended Memory,  
  800. except that it uses a 32-bit instead of a 16-bit value to specify the  
  801. amount of memory requested.  It allocates from the same memory and handle  
  802. pool as the current function.  Since it requires a 32-bit register, this
  803. function can be supported only on 80386 and higher processors, and XMS 
  804. drivers on 80286 machines should return error code 80h.
  805.  
  806.  
  807. Get Extended EMB Handle Information (Function 8Eh):
  808. ---------------------------------------------------
  809.  
  810.      Entry:
  811.             AH  = 8Eh
  812.             DX  = Extended memory block handle.
  813.      Exit:
  814.             AX  = 0001h if the block's information is found, 
  815.                 = 0000h if not
  816.             BH  = Block lock count
  817.             CX  = Number of free EMB handles in the system
  818.             EDX = Block's length in Kb.
  819.      Errors:
  820.             BL  = 80h if the function is not implemented.
  821.             BL  = 81h if a VDISK device is detected.
  822.             BL  = A2h if the handle is invalid.
  823.  
  824.     This function is similar to the Get EMB Handle Information function.  
  825. Since it uses a 32-bit register to report the block size, it can be used 
  826. to get information on blocks larger than 64 Mb.  It also uses a 16-bit 
  827. instead of 8-bit register to report the number of free handles, allowing 
  828. the handle pool to be extended beyond 256 entries.
  829.  
  830.     Because of its reliance on a 32-bit register, this function is 
  831. available on 80386 and higher processors.  XMS drivers on 80286 machines 
  832. should return error code 80h if this function is called.
  833.  
  834.  
  835. Reallocate Any Extended Memory (Function 8Fh):
  836. ----------------------------------------------
  837.  
  838.      Entry:
  839.             AH  = 8Fh
  840.             EBX = New size for extended memory block, in Kb.
  841.             DX  = Unlocked handle for memory block to be resized.
  842.      Exit:
  843.             AX  = 0001h if the block is reallocated, 
  844.                 = 0000h if not
  845.      Errors:
  846.             BL  = 80h if the function is not implemented.
  847.             BL  = 81h if a VDISK device is detected.
  848.             BL  = A0h if all available extended memory is allocated.
  849.             BL  = A1h if all available extended memory handles
  850.                   are in use.
  851.             BL  = A2h if the handle is invalid.
  852.             BL  = ABh if the block is locked.
  853.  
  854.     This function is similar to the existing Reallocate Extended
  855. Memory, except that it uses a 32-bit instead of a 16-bit value to specify  
  856. the amount of memory requested.  It allocates from the same memory and  
  857. handle pool as the current function.  Since it requires a 32-bit register, 
  858. this function can be supported only on 80386 and higher processors, and 
  859. XMS drivers on 80286 machines should return error code 80h.
  860.  
  861.  
  862.  
  863.  
  864. PRIORITIZING HMA USAGE:
  865. -----------------------
  866.  
  867.     For DOS users to receive the maximum benefit from the High Memory 
  868. Area, programs which use the HMA must store as much of their resident 
  869. code in it as is possible.  It is very important that developers realize
  870. that the HMA is allocated as a single unit.
  871.  
  872.     For example, a TSR program which grabs the HMA and puts 10K of code 
  873. into it may prevent a later TSR from putting 62K into the HMA.
  874. Obviously, regular DOS programs would have more memory available to 
  875. them below the 640K line if the 62K TSR was moved into the HMA instead 
  876. of the 10K one.
  877.  
  878.     The first method for dealing with conflicts such as this is to 
  879. require programs which use the HMA to provide a command line option
  880. for disabling this feature.  It is crucial that TSRs which do not make
  881. full use of the HMA provide such a switch on their own command line 
  882. (suggested name "/NOHMA").
  883.  
  884.     The second method for optimizing HMA usage is through the /HMAMIN=
  885. parameter on the XMS device driver line.  The number after the parameter
  886. is defined to be the minimum amount of HMA space (in K-bytes) used by any
  887. driver or TSR. For example, if "DEVICE=HIMEM.SYS /HMAMIN=48" is in a
  888. user's CONFIG.SYS file, only programs which request at least 48K would 
  889. be allowed to allocate the HMA.  This number can be adjusted either by
  890. installation programs or by the user himself.  If this parameter is not
  891. specified, the default value of 0 is used causing the HMA to be 
  892. allocated on a first come, first served basis.
  893.  
  894.     Note that this problem does not impact application programs.  If 
  895. the HMA is available when an application program starts, the application 
  896. is free to use as much or as little of the HMA as it wants.  For 
  897. this reason, applications should pass FFFFh in DX when calling 
  898. Function 01h.
  899.  
  900.  
  901.  
  902. HIGH MEMORY AREA RESTRICTIONS:
  903. ------------------------------
  904.  
  905. -  Far pointers to data located in the HMA cannot be passed to DOS. 
  906.    DOS normalizes any pointer which is passed into it.  This will 
  907.    cause data addresses in the HMA to be invalidated.
  908.  
  909. -  Disk I/O directly into the HMA (via DOS, INT 13h, or otherwise) is 
  910.    not recommended.
  911.  
  912. -  Programs, especially drivers and TSRs, which use the HMA *MUST* 
  913.    use as much of it as possible.  If a driver or TSR is unable
  914.    to use at least 90% of the available HMA (typically ~58K), 
  915.    they must provide a command line switch for overriding HMA usage.  
  916.    This will allow the user to configure his machine for optimum use 
  917.    of the HMA.
  918.  
  919. -  Device drivers and TSRs cannot leave the A20 line permanently 
  920.    turned on.  Several applications rely on 1MB memory wrap and
  921.    will overwrite the HMA if the A20 line is left enabled potentially 
  922.    causing a system crash.
  923.  
  924. -  Interrupt vectors must not point into the HMA.  This is a result of
  925.    the previous restriction.  Note that interrupt vectors can point 
  926.    into any allocated upper memory blocks however.
  927.  
  928. ERROR CODE INDEX:
  929. -----------------
  930.  
  931. If AX=0000h when a function returns and the high bit of BL is set,
  932.  
  933.    BL = 80h if the function is not implemented
  934.         81h if a VDISK device is detected
  935.         82h if an A20 error occurs
  936.         8Eh if a general driver error occurs
  937.         8Fh if an unrecoverable driver error occurs
  938.         90h if the HMA does not exist
  939.         91h if the HMA is already in use
  940.         92h if DX is less than the /HMAMIN= parameter
  941.         93h if the HMA is not allocated
  942.         94h if the A20 line is still enabled
  943.         A0h if all extended memory is allocated
  944.         A1h if all available extended memory handles are in use
  945.         A2h if the handle is invalid
  946.         A3h if the SourceHandle is invalid
  947.         A4h if the SourceOffset is invalid
  948.         A5h if the DestHandle is invalid
  949.         A6h if the DestOffset is invalid
  950.         A7h if the Length is invalid
  951.         A8h if the move has an invalid overlap
  952.         A9h if a parity error occurs
  953.         AAh if the block is not locked
  954.         ABh if the block is locked
  955.         ACh if the block's lock count overflows
  956.         ADh if the lock fails
  957.         B0h if a smaller UMB is available
  958.         B1h if no UMBs are available
  959.         B2h if the UMB segment number is invalid
  960.  
  961.  
  962. IMPLEMENTATION NOTES FOR DOS XMS DRIVERS:
  963. -----------------------------------------
  964.  
  965. -  A DOS XMS driver's control function must begin with code similar 
  966.    to the following:
  967.  
  968. XMMControl  proc   far
  969.  
  970.     jmp  short XCControlEntry   ; For "hookability"
  971.     nop                         ; NOTE: The jump must be a short
  972.     nop                         ; jump to indicate the end of
  973.     nop                         ; any hook chain.  The nop's
  974.                                 ; allow a far jump to be patched in.
  975. XCControlEntry:
  976.  
  977.  
  978. -  XMS drivers must preserve all registers except those containing
  979.    returned values across any function call.
  980.  
  981. -  XMS drivers are required to hook INT 15h and watch for calls to
  982.    functions 87h (Block Move) and 88h (Extended Memory Available).  
  983.    The INT 15h Block Move function must be hooked so that the
  984.    state of the A20 line is preserved across the call.  The INT 15h 
  985.    Extended Memory Available function must be hooked to return 0h to
  986.    protect the HMA.
  987.  
  988. -  In order to maintain compatibility with existing device drivers, 
  989.    DOS XMS drivers must not hook INT 15h until the first non-Version 
  990.    Number callto the control function is made.
  991.  
  992. -  XMS drivers are required to check for the presence of drivers which
  993.    use the IBM VDISK allocation scheme.  Note that it is not sufficient 
  994.    to check for VDISK users at installation time but at the time when 
  995.    the HMA is first allocated.  If a VDISK user is detected, the
  996.    HMA must not be allocated. Microsoft will publish a standard method 
  997.    for detecting drivers which use the VDISK allocation scheme.
  998.  
  999. -  XMS drivers which have a fixed number of extended memory handles 
  1000.    (most do) should implement a command line parameter for adjusting 
  1001.    that number (suggested name "/NUMHANDLES=")
  1002.  
  1003. -  XMS drivers should make sure that the major DOS version number is
  1004.    greater than or equal to 3 before installing themselves.
  1005.  
  1006. -  UMBs cannot occupy memory addresses that can be banked by EMS 4.0.
  1007.    EMS 4.0 takes precedence over UMBs for physically addressable memory.
  1008.  
  1009. -  All driver functions must be re-entrant.  Care should be taken to 
  1010.    not leave interrupts disabled for long periods of time.
  1011.  
  1012. -  Allocation of a zero length extended memory buffer is allowed.  
  1013.    Programs which hook XMS drivers may need to reserve a handle for
  1014.    private use via this method.  Programs which hook an XMS driver 
  1015.    should pass all requests for zero length EMBs to the next driver in 
  1016.    the chain.
  1017.  
  1018. -  Drivers should control the A20 line via an "enable count."  Local 
  1019.    Enable only enables the A20 line if the count is zero.  It then 
  1020.    increments the count.  Local Disable only disables A20 if the count
  1021.    is one.  It then decrements the count.  Global Enable/Disable
  1022.    keeps a flag which indicates the state of A20.  They use Local
  1023.    Enable/Disable to actually change the state.
  1024.  
  1025. -  Drivers should always check the physical A20 state in the
  1026.    local Enable-Disable calls, to see that the physical state matches 
  1027.    the internal count.  If the physical state does not match, it should
  1028.    be modified so that it matches the internal count.  This avoids 
  1029.    problems with applications that modify A20 directly.
  1030.  
  1031.  
  1032. IMPLEMENTATION OF CODE FOR HOOKING THE XMS DRIVER:
  1033. --------------------------------------------------
  1034.  
  1035.     In order to support the hooking of the XMS driver by multiple 
  1036. pieces of code, the following code sample should be followed.  Use of 
  1037. other methods for hooking the XMS driver will not work in many cases. 
  1038. This method is the official supported one.
  1039.  
  1040. The basic strategy is:
  1041.  
  1042.     Find the XMS driver header which has the "near jump" dispatch.
  1043.  
  1044.     Patch the near jump to a FAR jump which jumps to my HOOK XMS
  1045.     driver header.
  1046.  
  1047.   NOTES:
  1048.  
  1049.     o This architecture allows the most recent HOOKer to undo his
  1050.       XMS driver hook at any time without having to worry about
  1051.       damaging a "hook chain".
  1052.  
  1053.     o This architecture allows the complete XMS hook chain to be
  1054.       enumerated at any time.  There are no "hidden hooks".
  1055.  
  1056.     o This architecture allows the HOOKer to not have to worry
  1057.       about installing an "INT 2F hook" to hook the AH=43h
  1058.       INT 2Fs handled by the XMS driver.  The base XMS driver
  1059.       continues to be the only one installed on INT 2Fh AH=43h.
  1060.  
  1061.       This avoids all of the problems of undoing a software
  1062.       interrupt hook.
  1063.  
  1064.   ;
  1065.   ; When I wish to CHAIN to the previous XMS driver, I execute a FAR JMP
  1066.   ;     to the address stored in this DWORD.
  1067.   ;
  1068.   PrevXMSControlAddr   dd    ?
  1069.  
  1070.   ;
  1071.   ; The next two data items are needed ONLY if I desire to be able to
  1072.   ;     undo my XMS hook.
  1073.   ; PrevXMSControlJmpVal stores the previos XMS dispatch near jump 
  1074.   ;     offset value that is used to unhook my XMS hook
  1075.   ; PrevXMSControlBase stores the address of the XMS header that I hooked
  1076.   ;
  1077.   PrevXMSControlBase   dd    ?
  1078.   PrevXMSControlJmpVal db    ?
  1079.  
  1080.   ;
  1081.   ; This is MY XMS control header.
  1082.   ;
  1083.   MyXMSControlFunc proc FAR
  1084.         jmp   short XMSControlEntry
  1085.         nop
  1086.         nop
  1087.         nop
  1088.   XMSControlEntry:
  1089.  
  1090.   ......
  1091.  
  1092.   Chain:
  1093.         jmp   cs:[PrevXMSControlAddr]
  1094.  
  1095.   MyXMSControlFunc endp
  1096.  
  1097.  
  1098.   ......
  1099.   
  1100.   ;
  1101.   ; This is the code which installs my hook into the XMS driver.
  1102.   ;
  1103.     ;
  1104.     ; See if there is an XMS driver to hook
  1105.     ;
  1106.         mov   ax,4300h
  1107.         int   2Fh
  1108.         cmp   al,80h
  1109.         jne   NoXMSDrvrToHookError
  1110.     ;
  1111.     ; Get the current XMS driver Control address
  1112.     ;
  1113.         mov   ax,4310h
  1114.         int   2Fh
  1115.   NextXMSHeader:
  1116.         mov   word ptr [PrevXMSControlAddr+2],es
  1117.         mov   word ptr [PrevXMSControlBase+2],es
  1118.         mov   word ptr [PrevXMSControlBase],bx
  1119.         mov   cx,word ptr es:[bx]
  1120.         cmp   cl,0EBh                         ; Near JUMP
  1121.         je    ComputeNearJmp
  1122.         cmp   cl,0EAh                         ; Far JUMP
  1123.         jne   XMSDrvrChainMessedUpError
  1124.   ComputeFarJmp:
  1125.         mov   si,word ptr es:[bx+1]           ; Offset of jump
  1126.         mov   es,word ptr es:[bx+1+2]         ; Seg ofjump
  1127.         mov   bx,si
  1128.         jmp   short NextXMSHeader
  1129.  
  1130.   ComputeNearJmp:
  1131.         cmp   word ptr es:[bx+2],9090h        ; Two NOPs?
  1132.         jne   XMSDrvrChainMessedUpError       ; No
  1133.         cmp   byte ptr es:[bx+4],90h          ; Total of 3 NOPs?
  1134.         jne   XMSDrvrChainMessedUpError       ; No
  1135.         mov   di,bx                           ; Save pointer to header
  1136.         xor   ax,ax
  1137.         mov   al,ch                           ; jmp addr of near jump
  1138.         mov   [PrevXMSControlJmpVal],al
  1139.         add   ax,2                            ; NEAR JMP is 2 byte 
  1140.                                               ; instruction
  1141.         add   bx,ax                           ; Target of jump
  1142.         mov   word ptr [PrevXMSControlAddr],bx
  1143.     ;
  1144.     ; Now INSTALL my XMS HOOK
  1145.     ;
  1146.         cli                                   ; Disable INTs in
  1147.                                               ; case someone calls
  1148.                                               ; XMS at interrupt time
  1149.         mov   byte ptr es:[di],0EAh           ; Far Immed. JUMP 
  1150.                                               ; instruction 
  1151.         mov   word ptr es:[di+1],offset MyXMSControlFunc
  1152.         mov   word ptr es:[di+3],cs
  1153.         sti
  1154.     
  1155.     .....
  1156.  
  1157.     ;
  1158.     ; Deinstall my XMS hook. This can be done IF AND ONLY IF my XMS header
  1159.     ;   still contains the near jump dispatch
  1160.     ;
  1161.         cmp   byte ptr [MyXMSControlFunc],0EBh
  1162.         jne   CantDeinstallError
  1163.         mov   al,0EBh
  1164.         mov   ah,[PrevXMSControlJmpVal]
  1165.         les   bx,[PrevXMSControlBase]
  1166.         cli                                   ; Disable INTs in case 
  1167.                                               ; someone calls XMS at
  1168.                                               ; interrupt time
  1169.         mov   word ptr es:[bx],ax
  1170.         mov   word ptr es:[bx+2],9090h
  1171.         mov   byte ptr es:[bx+4],90h
  1172.         sti
  1173.         
  1174.     .....
  1175.  
  1176.  
  1177. IMPLEMENTATION NOTES FOR HIMEM.SYS:
  1178. -----------------------------------
  1179.  
  1180. -  HIMEM.SYS currently supports true AT-compatibles, 386 AT machines, 
  1181.    IBM PS/2s, AT&T 6300 Plus systems and Hewlett Packard Vectras.
  1182.  
  1183. -  If HIMEM finds that it cannot properly control the A20 line or if 
  1184.    there is no extended memory available when HIMEM.SYS is invoked, 
  1185.    the driver does not install itself.  HIMEM.SYS displays the message
  1186.    "High Memory Area Unavailable" when this situation occurs.
  1187.  
  1188. -  If HIMEM finds that the A20 line is already enabled when it is 
  1189.    invoked, it will NOT change the A20 line's state.  The assumption
  1190.    is that whoever enabled it knew what they were doing.  HIMEM.SYS
  1191.    displays the message "A20 Line Permanently Enabled" when this 
  1192.    situation occurs.
  1193.  
  1194. -  HIMEM.SYS is incompatible with IBM's VDISK.SYS driver and other 
  1195.    drivers which use the VDISK scheme for allocating extended memory.  
  1196.    However, HIMEM does attempt to detect these drivers and will not
  1197.    allocate the HMA if one is found.
  1198.  
  1199. -  HIMEM.SYS supports the optional "/HMAMIN=" parameter. The valid values
  1200.    are decimal numbers between 0 and 63.
  1201.  
  1202. -  By default, HIMEM.SYS has 32 extended memory handles available for 
  1203.    use.  This number may be adjusted with the "/NUMHANDLES=" parameter.  
  1204.    The maximum value for this parameter is 128 and the minimum is 0.  
  1205.    Each handle currently requires 6 bytes of resident space.
  1206.  
  1207.  
  1208. Copyright (C) 1988, Microsoft Corporation
  1209.